﻿//-----------------------------------------------------------------------
// <copyright file="BingTiledMapResource.cs" company="WorldView Solutions Inc">
//     Copyright (c) WorldView Solutions Inc. This source is subject to the Microsoft Public License (Ms-PL). All other rights reserved.
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WorldViewSolutions.ArcGISServer.SOE.DataSources
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks></remarks>
	public class BingTiledMapResource : TiledMapResource
	{
        /// <summary>
        /// Gets or sets the bing maps key.
        /// </summary>
        /// <value>The bing maps key.</value>
        /// <remarks></remarks>
		public string BingMapsKey { get; set; }
        /// <summary>
        /// Gets or sets the culture.
        /// </summary>
        /// <value>The culture.</value>
        /// <remarks></remarks>
		public string Culture { get; set; }
        /// <summary>
        /// Gets or sets the imagery set.
        /// </summary>
        /// <value>The imagery set.</value>
        /// <remarks></remarks>
		public string ImagerySet { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="BingTiledMapResource"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="serviceUrls">The service urls.</param>
        /// <param name="bingMapsKey">The bing maps key.</param>
        /// <param name="culture">The culture.</param>
        /// <param name="imagerySet">The imagery set.</param>
        /// <remarks></remarks>
		public BingTiledMapResource(string name, string[] serviceUrls, string bingMapsKey, string culture, string imagerySet) : base()
        {

			this.Name = name;
			this.ServiceUrls = serviceUrls;
			this.BingMapsKey = bingMapsKey;
			this.Culture = culture;
			this.ImagerySet = imagerySet;

			this.TileCacheInfo = new ESRI.ArcGIS.ADF.ArcGISServer.TileCacheInfo();
			this.TileCacheInfo.DPI = 96;
			this.TileCacheInfo.TileRows = 256;
			this.TileCacheInfo.TileCols = 256;
						
			ESRI.ArcGIS.ADF.ArcGISServer.PointN origin = new ESRI.ArcGIS.ADF.ArcGISServer.PointN();
			origin.X = -20037508.342787001;
			origin.Y = 20037508.342787001;
			this.TileCacheInfo.TileOrigin = origin;

			System.Collections.Generic.List<ESRI.ArcGIS.ADF.ArcGISServer.LODInfo> lodInfos = new List<ESRI.ArcGIS.ADF.ArcGISServer.LODInfo>();
			lodInfos.Add(CreateLOD(0, 591657527.591555, 156543.03392800014));
			lodInfos.Add(CreateLOD(1, 295828763.79577702, 78271.516963999937));
			lodInfos.Add(CreateLOD(2, 147914381.89788899, 39135.758482000092));
			lodInfos.Add(CreateLOD(3, 73957190.948944002, 19567.879240999919));
			lodInfos.Add(CreateLOD(4, 36978595.474472001, 9783.9396204999593));
			lodInfos.Add(CreateLOD(5, 18489297.737236001, 4891.9698102499797));
			lodInfos.Add(CreateLOD(6, 9244648.8686180003, 2445.9849051249898));
			lodInfos.Add(CreateLOD(7, 4622324.4343090001, 1222.9924525624949));
			lodInfos.Add(CreateLOD(8, 2311162.2171550002, 611.49622628137968));
			lodInfos.Add(CreateLOD(9, 1155581.108577, 305.74811314055756));
			lodInfos.Add(CreateLOD(10, 577790.55428899999, 152.87405657041106));
			lodInfos.Add(CreateLOD(11, 288895.27714399999, 76.437028285073239));
			lodInfos.Add(CreateLOD(12, 144447.638572, 38.21851414253662));
			lodInfos.Add(CreateLOD(13, 72223.819285999998, 19.10925707126831));
			lodInfos.Add(CreateLOD(14, 36111.909642999999, 9.5546285356341549));
			lodInfos.Add(CreateLOD(15, 18055.954822, 4.7773142679493699));
			lodInfos.Add(CreateLOD(16, 9027.9774109999998, 2.3886571339746849));
			lodInfos.Add(CreateLOD(17, 4513.9887049999998, 1.1943285668550503));
			lodInfos.Add(CreateLOD(18, 2256.994353, 0.59716428355981721));
			lodInfos.Add(CreateLOD(19, 1128.4971760000001, 0.29858214164761665));

			this.TileCacheInfo.LODInfos = lodInfos.ToArray();

			this.TileImageInfo = new ESRI.ArcGIS.ADF.ArcGISServer.TileImageInfo();
			this.TileImageInfo.CompressionQuality = 0;
			this.TileImageInfo.CacheTileFormat = "PNG8";
			
        }

        /// <summary>
        /// Creates the LOD.
        /// </summary>
        /// <param name="level">The level.</param>
        /// <param name="scale">The scale.</param>
        /// <param name="resolution">The resolution.</param>
        /// <returns></returns>
        /// <remarks></remarks>
		private ESRI.ArcGIS.ADF.ArcGISServer.LODInfo CreateLOD(int level, double scale, double resolution)
		{
			ESRI.ArcGIS.ADF.ArcGISServer.LODInfo lodInfo = new ESRI.ArcGIS.ADF.ArcGISServer.LODInfo();
			lodInfo.LevelID = level;
			lodInfo.Resolution = resolution;
			lodInfo.Scale = scale;
			return lodInfo;
		}

        /// <summary>
        /// Gets the tile URL.
        /// </summary>
        /// <param name="level">The level.</param>
        /// <param name="column">The column.</param>
        /// <param name="row">The row.</param>
        /// <param name="vdir">The vdir.</param>
        /// <param name="imageType">Type of the image.</param>
        /// <returns></returns>
        /// <remarks></remarks>
		public override string GetTileUrl(int level, int column, int row, string vdir, string imageType)
		{
			string _bingQuadKey = GetVEQuadKey(level, row, column);


			switch (ImagerySet)
			{
				case "aerial":
				case "hybrid":
					//http://{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=507&mkt={culture}&token={token}
					return vdir + _bingQuadKey + ".jpeg?g=507&mkt=" + Culture + "&token=" + BingMapsKey;
				default: //road
					//http://{subdomain}.tiles.virtualearth.net/tiles/r{quadkey}.jpeg?g=507&mkt={culture}&shading=hill&token={token}
					return vdir + _bingQuadKey + ".jpeg?g=507&mkt=" + Culture + "&shading=hill&token=" + BingMapsKey;
			}
		}

        /// <summary>
        /// Gets the VE quad key.
        /// </summary>
        /// <param name="level">The level.</param>
        /// <param name="row">The row.</param>
        /// <param name="col">The col.</param>
        /// <returns></returns>
        /// <remarks></remarks>
		private string GetVEQuadKey(int level, int row, int col)
		{
			string quadKey = "";
			int d, mask;

			for (var i = level; i > 0; i--)
			{
				d = 0;
				mask = 1 << (i - 1);
				if ((col & mask) != 0)
				{
					d++;
				}
				if ((row & mask) != 0)
				{
					d++; d++;
				}
				quadKey = quadKey + d;
			}
			return quadKey;
		}
	}
}
